package com.dant.components
{
	import com.dant.components.containers.panels.MenuPanel;
	
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
	
	import mx.collections.XMLListCollection;
	import mx.controls.Tree;
	import mx.controls.scrollClasses.ScrollThumb;
	import mx.core.DragSource;
	import mx.events.DragEvent;
	import mx.events.ListEvent;
	
	
	//events
	[Event(name="click", type="flash.events.MouseEvent")]
	[Event(name="itemClick", type="mx.events.ListEvent")]
	[Event(name="change", type="mx.events.ListEvent")]
	[Event(name="dragDrop", type="mx.events.DragEvent")]
	[DefaultProperty("dataProvider")]
	public class TreeMenu extends MenuPanel
	{
		// tree variables
		
		private var _tree:Tree = new Tree();
		
		private var _selectedItem:Object;
		
		private var _isDraggingItem:Boolean;

		[Inspectable(type="Boolean")]
		public var showRoot:Boolean;


		[Inspectable(type="Boolean")]		
		public function set dragEnabled ( value: Boolean ) : void
		{
			_tree.dragEnabled = value;
		}
		
		[Inspectable(type="Boolean")]
		public function set dropEnabled ( value: Boolean ) : void
		{
/* 
			if ( ! _tree.hasEventListener(DragEvent.DRAG_DROP) && value )
			{
				_tree.addEventListener( DragEvent.DRAG_DROP, dropXML );
			}
			else if ( ! value )
			{
				_tree.removeEventListener( DragEvent.DRAG_DROP, dropXML);
			}
 */
			this._tree.dropEnabled = value;
		}
		
		[Inspectable(type="Boolean")]
		public function set dragMoveEnabled ( value: Boolean ) : void
		{
			_tree.dragMoveEnabled = value;
		}		
		
		public function get dragEnabled ( ) : Boolean
		{
			if (_tree)
			{
				return ( _tree.dragEnabled );
			}
			return (false);
		}

		public function get dropEnabled ( ) : Boolean
		{
			if (_tree)
			{
				return ( _tree.dropEnabled );
			}
			return (false);
		}
		
		public function get dragMoveEnabled ( ) : Boolean
		{
			if (_tree)
			{
				return ( _tree.dragMoveEnabled );
			}
			return (false);
		}		

		[Inspectable(type="String")]
		public function set labelField ( value: String ) : void
		{
			_tree.labelField = value;
		}		
		
		public function get labelField ( ) : String
		{
			if (_tree)
			{
				return ( _tree.labelField );
			}
			return (null);
		}		
		
		[Inspectable]
		public function set dataProvider ( value: Object ) : void
		{
			_tree.dataProvider = value;
		}

		public function get dataProvider ( ) : Object
		{
			if (_tree)
			{
				return ( _tree.dataProvider );
			}
			return (null);
		}
		
		public function get selectedItem ( ) : Object
		{
			if (_tree)
			{
				return ( _tree.selectedItem );
			}
			return (null);
		}
		
		public function get selectedIndex ( ) : Object
		{
			if (_tree)
			{
				return ( _tree.selectedIndex );
			}
			return (null);
		}

		public function TreeMenu ( )
		{
			super ( );
		}
		
		override protected function createChildren ( ) :void
		{
			super.createChildren();
			
			// _tree initialization
			_tree.showRoot = showRoot;
			_tree.percentHeight = 100;
			_tree.percentWidth = 100;
			_tree.setStyle("backgroundAlpha",0);
			_tree.addEventListener(ListEvent.CHANGE,changeDispatcher,false,0,true);
			_tree.addEventListener(ListEvent.ITEM_CLICK,itemClickDispatcher,false,0,true);
			_tree.addEventListener(MouseEvent.CLICK,clickDispatcher,false,0,true);
			_tree.addEventListener(DragEvent.DRAG_START, dragStartHandler,false,0,true);
			_tree.addEventListener(DragEvent.DRAG_DROP, dragDropHandler,false,0,true);
		
			addChild(_tree);
			
			_isDraggingItem = false;
		}
		
		public function changeDispatcher ( event:ListEvent ):void
		{
			if (event.currentTarget.selectedItem && !_isDraggingItem)
			{
				var selectedItemString:String = event.currentTarget.selectedItem..toString();
				var xmlCollection : XMLListCollection = new XMLListCollection (event.currentTarget.selectedItem.descendants());
				
				//if ( selectedItemString.search("folder") > 0 ) 
				if ( xmlCollection && xmlCollection.length )//&& event.currentTarget.selectedItem.descendants().length > 0 )
				{
					_tree.expandItem( event.currentTarget.selectedItem, !(_tree.isItemOpen( event.currentTarget.selectedItem )), true );
				}
				else
				{
					this.dispatchEvent( event );
				}
			}
			_isDraggingItem = false;
		}
		
		public function itemClickDispatcher ( event:ListEvent ):void
		{
			if (event.currentTarget.selectedItem && !_isDraggingItem && !(event.target is ScrollThumb))
			{
				var selectedItemString:String = event.currentTarget.selectedItem..toString();
				var xmlCollection : XMLListCollection = new XMLListCollection (event.currentTarget.selectedItem.descendants());
				
				//if ( selectedItemString.search("folder") > 0 ) 
				if ( xmlCollection && xmlCollection.length )//&& event.currentTarget.selectedItem.descendants().length > 0 )
				{
					_tree.expandItem( event.currentTarget.selectedItem, !(_tree.isItemOpen( event.currentTarget.selectedItem )), true );
				}
				else
				{
					this.dispatchEvent( event );
				}
			}
			_isDraggingItem = false;
		}
		
		public function clickDispatcher ( event : MouseEvent ) : void
		{
			if (event.currentTarget.selectedItem && !_isDraggingItem && !(event.target is ScrollThumb))
			{
				var selectedItemString:String = event.currentTarget.selectedItem..toString();
				var xmlCollection : XMLListCollection = new XMLListCollection (event.currentTarget.selectedItem.descendants());
				
				//if ( selectedItemString.search("folder") > 0 ) 
				if ( xmlCollection && xmlCollection.length )//&& event.currentTarget.selectedItem.descendants().length > 0 )
				{
					_tree.expandItem( event.currentTarget.selectedItem, !(_tree.isItemOpen( event.currentTarget.selectedItem )), true );
				}
				else
				{
					this.dispatchEvent( event );
				}
			}
			_isDraggingItem = false;
		}

		private function dragStartHandler ( event : MouseEvent ) : void
		{
			_isDraggingItem = true;
			trace ( event.currentTarget );
		}
		
		private function dragDropHandler ( event : MouseEvent ) : void
		{
			_isDraggingItem = false;
			trace ( event.currentTarget );
		}
		
		// THIS IS ALREADY IMPLEMENTED IN FLEX 3. CAN BE DELETED.
        private function dropXML ( event : DragEvent ):void
        {
        	// gets the data that is being dragged. The format of the data being dragged
        	// is in the formats attributte.
        	var ds:DragSource = event.dragSource;
        	
        	// the _tree the data is dropped into. It should be this _tree.
        	var dropTarget:Tree = Tree(event.currentTarget);

		   	// if the drag source has the "_tree items" format
		   	if ( ds.hasFormat("treeItems") )
		   	{
			    // retrieve the data associated with the "items" format. This will be the data that
			    // the dragInitiator has copied into the DragSource.
			    var items:Array = ds.dataForFormat("treeItems") as Array;
	
				// if the target doesn't have a dataProvider it is created
				if (! dropTarget.dataProvider)
				{
					dropTarget.dataProvider = new XMLList();
				}

				// if the target doesn't contains the data being dragged, it is added.
				if (! dropTarget.dataProvider.contains(items[0]))
				{
//					dropTarget.dataProvider.addItem(items[0]);
			 	}
		   	}
        }
		
		public function addChildToTree ( value:DisplayObject ):void
		{
			_tree.addChild( value );
		}
		
		public function addChildToTreeAt ( value:DisplayObject , index:Number ):void
		{
			_tree.addChildAt( value , index );
		}
		
		public function containedInTree ( child:DisplayObject ) : Boolean
		{
			return ( _tree.contains( child ) );
		}
		
		public function findString ( str:String ) : Boolean
		{
			return ( _tree.findString( str ) );
		}
		
		public function getTreeChildAt ( index : int ) : DisplayObject
		{
			return ( _tree.getChildAt(index) );
		}

		public function getTreeChildByName ( name : String ) : DisplayObject
		{
			return ( _tree.getChildByName(name) );
		}
		
		public function getTreeChildIndex ( child : DisplayObject ) : int
		{
			return ( _tree.getChildIndex(child) );
		}
		
		public function getParentItem ( item : Object ) : Object
		{
			return ( _tree.getParentItem(item) );
		}
		
		public function isItemOpen ( item:Object ) : Boolean
		{
			return ( _tree.isItemOpen( item ) );
		}
		
		public function isItemHighlighted ( item:Object ) : Boolean
		{
			return ( _tree.isItemHighlighted( item ) );
		}
		
		public function isItemSelected ( item:Object ) : Boolean
		{
			return ( _tree.isItemSelected( item ) );
		}
		
		public function isItemVisible ( item:Object ) : Boolean
		{
			return ( _tree.isItemVisible ( item ) );
		}

		public function removeTreeChild ( child:DisplayObject ) : DisplayObject
		{
			return ( _tree.removeChild ( child ) );
		}
		
		public function removeTreeChildAt ( index:int ) : DisplayObject
		{
			return ( _tree.removeChildAt( index ) );
		}
	}
}